import { Message } from "@arco-design/web-vue";
import Cookies from "js-cookie";
import type { FetchResponse } from "ofetch";

export type CommonReturn<T = any> = {
	code: number;
	data: T;
	message: string;
};

type RequestConf = {
	isTransform?: boolean;
	errorMessageMode?: "none";
	unauthorizedToLogin?: boolean;
};

function handleResError<T>(response: FetchResponse<T>) {
	const handleMap: Record<number, () => void> = {
		404: () => Message.error("资源不存在"),
		403: () => {
			navigateTo("/");
		},
		401: () => {
			navigateTo("/");
		}
	};
	handleMap[response.status] && handleMap[response.status]();
	// : Message.error('请求失败，请稍后重试')
}
type FetchOptions = Parameters<typeof $fetch>[1];

async function requestFn<T>(url: string, options: FetchOptions, config: RequestConf = {}): Promise<CommonReturn<T>> {
	const conf = {
		isTransform: true,
		errorMessageMode: "none",
		unauthorizedToLogin: true,
		...(config || {})
	};
	const {
		public: { langKey, tokenKey }
	} = useRuntimeConfig();

	let localeLang = "";
	let token = "";
	const client = import.meta.client;
	if (client) {
		localeLang = Cookies.get(langKey) || "zh-CN";
		token = Cookies.get(tokenKey) || "";
	}
	await nextTick();
	const opts: FetchOptions = {
		...options,
		retry: 3,
		retryDelay: 500,
		timeout: 15000,
		responseType: "json",
		onRequest({ options }) {
			const {
				public: { apiBase }
			} = useRuntimeConfig();

			options.baseURL = apiBase as string;
			options.timeout = 15000;
			options.headers = new Headers(options.headers);
			if (token) {
				options.headers.set("Authorization", `Bearer ${token}`);
			}
			if (options?.method?.toLowerCase() !== "get") {
				options.headers.set("Content-Type", `application/json;charset=UTF-8`);
			}
			options.headers.set("accept-language", localeLang ?? "zh-CN");

			options.mode = "cors";
			options.credentials = "include";
		},
		onResponse: ({ response }) => {
			const res = response._data;

			const isSuccess = response.status === 200 && String(res.code).endsWith("6200");
			const { message } = res;

			if (isSuccess) {
				return res;
			}
			if (String(res.code).endsWith("6401")) {
				Message.error("未登录或登录已过期");
				throw new Error("未登录或登录已过期");
			} else if (String(res.code).endsWith("6404")) {
				conf?.errorMessageMode !== "none" &&
					showError({
						statusCode: 404,
						message: "资源不存在"
					});
			} else {
				Message.error(message ?? "请求失败，请稍后重试");
				return undefined;
			}
		},
		onResponseError({ response }) {
			handleResError(response);
		}
	};

	return $fetch(url, opts).catch(() => {
		Message.error("请求失败，请稍后重试");
	}) as Promise<CommonReturn<T>>;
}

export const useHttp = {
	get: <T>(url: string, params?: any, config?: RequestConf, options?: FetchOptions) => {
		return requestFn<T>(
			url,
			{
				method: "GET",
				params,
				...{ isTransform: true, ...(options || {}) }
			},
			config
		);
	},
	post: <T>(url: string, body?: any, config?: RequestConf, options?: FetchOptions) => {
		return requestFn<T>(url, { method: "POST", body, ...{ isTransform: true, ...(options || {}) } }, config);
	},
	put: <T>(url: string, body?: any, config?: RequestConf, options?: FetchOptions) => {
		return requestFn<T>(url, { method: "put", body, ...{ isTransform: true, ...(options || {}) } }, config);
	},

	delete: <T>(url: string, body?: any, config?: RequestConf, options?: FetchOptions) => {
		return requestFn<T>(url, { method: "delete", body, ...{ isTransform: true, ...(options || {}) } }, config);
	}
};
